package validjson;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ArrayValidator implements Validator {
    private final Schema schema;
    private final ValidatorFactory validatorFactory;

    public ArrayValidator(Schema schema, ValidatorFactory validatorFactory) {
        this.schema = schema;
        this.validatorFactory = validatorFactory;
    }

    public void validate(Object jsonToValidate) throws ValidationException {
        if (!(jsonToValidate instanceof List)) {
            throw new ValidationException(String.format("Validator expected a value of type '%s' but got %s", "List", jsonToValidate == null ? null : jsonToValidate.getClass()));
        }

        List list = (List)jsonToValidate;

        if (schema.containsKey("maxItems")) {
            long maxItems = ((Number)schema.getValue("maxItems")).longValue();
            if (list.size() > maxItems) {
                throw new ValidationException("Value '" + list + "' has more items than the maximum " + maxItems);
            }
        }

        if (schema.containsKey("minItems")) {
            long minItems = ((Number)schema.getValue("minItems")).longValue();
            if (list.size() < minItems) {
                throw new ValidationException("Value '" + list + "' has more items than the minimum " + minItems);
            }
        }

        if (schema.containsKey("uniqueItems") && (Boolean)schema.getValue("uniqueItems")) {
            Set uniqueItems = new HashSet();
            for (Object item : list) {
                if (uniqueItems.contains(item)) {
                    throw new ValidationException("Value '" + list + "' contains duplicate items (e.g. '" + item + "')");
                } else {
                    uniqueItems.add(item);
                }
            }
        }

        try {
            Schema itemsSchema = schema.getSubSchema("items");
            for (Object item : list) {
                validatorFactory.createValidator(itemsSchema, item).validate(item);
            }
        } catch (IOException e) {
            throw new ValidationException("Cannot validate list items", e);
        }

    }
}
